package com.example.android.plugin.framework;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.example.android.plugin.framework.beans.Plugin;
import com.example.android.plugin.framework.beans.PluginFeatureBean;
import com.example.android.plugin.framework.beans.PluginFeatureMethod;
import com.example.android.plugin.framework.beans.PluginIntent;
import com.example.android.plugin.framework.util.Utils;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;

/**
 * 执行插件
 */
public class PluginInvoke {

	private Context context;

	/**
	 * 执行插件
	 * 
	 * @param context
	 *            参数context必须是主程序的句柄
	 */
	public PluginInvoke(Context context) {
		this.context = context;
	}

	/**
	 * 调用指定的插件的指定功能
	 * 
	 * @param plugin
	 * @param feature
	 *            功能描述
	 * @return
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 * @throws NameNotFoundException
	 * @throws NoSuchFieldException
	 */
	public Object invoke(Plugin plugin, PluginFeatureBean feature,
			PluginFeatureMethod method) throws ClassNotFoundException,
			IllegalAccessException, InstantiationException, SecurityException,
			NoSuchMethodException, IllegalArgumentException,
			InvocationTargetException, NameNotFoundException,
			NoSuchFieldException {

		Context targetContext = context.createPackageContext(
				plugin.getPkgInfo().packageName, Context.CONTEXT_INCLUDE_CODE
						| Context.CONTEXT_IGNORE_SECURITY);

		ClassLoader loader = Utils.changeClassLoaderParent(targetContext,
				context.getClassLoader());
		Class<?> c = loader.loadClass(feature.getFeatureName());
		Object pluginActivity = c.newInstance();

		Method target = null;
		if (method.needContext()) {
			target = c.getMethod(method.getMethodName(), Context.class);
			target.invoke(pluginActivity, context);
		} else {
			target = c.getMethod(method.getMethodName());
			target.invoke(pluginActivity);
		}

		return pluginActivity;
	}

	public void invoke(Plugin plugin, PluginIntent intent, Bundle extras)
			throws NameNotFoundException, NoSuchFieldException,
			IllegalAccessException, IllegalArgumentException {
		Context targetContext = context.createPackageContext(
				plugin.getPkgInfo().packageName, Context.CONTEXT_INCLUDE_CODE
						| Context.CONTEXT_IGNORE_SECURITY);
		Utils.changeClassLoaderParent(targetContext, context.getClassLoader());
		Intent i = intent.getIntent();
		i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		if (extras != null) {
			i.putExtras(extras);
		}
		targetContext.startActivity(i);
	}

	public void invoke(Plugin plugin, PluginIntent value)
			throws NameNotFoundException, NoSuchFieldException,
			IllegalAccessException, IllegalArgumentException {
		invoke(plugin, value, null);
	}

}
